from fastapi import APIRouter, Depends, Query, HTTPException, Path, Security
from app.database.database import get_db
from app.services.user_service import get_user_by_id
from app.services.file_service import (
    search_files, get_file_by_id, delete_file, rename_file, restore_file,
    get_file_preview_url, get_file_download_url, batch_delete_files, batch_restore_files
)
from sqlalchemy.orm import Session
from typing import Optional, List, Dict, Any
from datetime import datetime
import logging
from pydantic import BaseModel, Field
from app.services.auth_service import get_current_user
from fastapi.security import OAuth2PasswordBearer, SecurityScopes
from app.database.models import User
from app.utils.response_utils import ResponseResult
from app.core.config import settings
from app.schemas.file_schema import FileResponse, PaginatedResponse
from fastapi import Request
import time

# 配置日志记录器
logger = logging.getLogger(__name__)

oauth2_scheme = OAuth2PasswordBearer(
    tokenUrl="/auth/oauth/token",
    scheme_name="OAuth2PasswordBearer",
    auto_error=True
)

router = APIRouter(
    prefix="/api",
    tags=["文件管理"],
    responses={
        401: {"description": "未认证"},
        403: {"description": "无权限访问"},
        404: {"description": "资源不存在"},
        500: {"description": "服务器内部错误"}
    }
)

async def get_current_user_from_token(
    token: str = Depends(oauth2_scheme),
    db: Session = Depends(get_db)
) -> User:
    """从token中获取当前用户"""
    return get_current_user(db, token)

@router.get("/files", 
          response_model=ResponseResult[PaginatedResponse[FileResponse]], 
          tags=["文件管理"], 
          summary="获取文件列表", 
          description="获取当前用户的文件列表，支持分页、排序和各种过滤条件")
async def get_files(
    request: Request,
    db: Session = Depends(get_db),
    file_type: Optional[str] = Query(None, description="文件类型，可选值：photo, video, audio, document, other"),
    start_time: Optional[str] = Query(None, description="开始时间，格式：YYYY-MM-DD HH:MM:SS"),
    end_time: Optional[str] = Query(None, description="结束时间，格式：YYYY-MM-DD HH:MM:SS"),
    keyword: Optional[str] = Query(None, description="文件名关键词"),
    file_hash: Optional[str] = Query(None, description="文件哈希值"),
    page: int = Query(1, description="页码，从1开始"),
    page_size: int = Query(20, description="每页数量，默认20，最大100"),
    is_delete: Optional[bool] = Query(None, description="是否已删除，None表示不限，false表示未删除，true表示已删除"),
    order_by: str = Query("upload_time", description="排序字段"),
    order_desc: bool = Query(True, description="是否降序排序"),
    directory_id: Optional[int] = Query(None, description="目录ID，None表示不限目录，0表示仅查询根目录文件"),
    current_user: User = Depends(get_current_user_from_token)
):
    """查询文件列表，支持多种筛选条件和分页
    
    返回:
        - **total**: 符合条件的总文件数
        - **page**: 当前页码
        - **page_size**: 每页数量
        - **items**: 文件列表，每个文件包含完整的文件信息
    """
    logger.debug(f"接收到查询请求: user_id={current_user.id}, file_type={file_type}, keyword={keyword}, directory_id={directory_id}")
    
    # 验证时间格式
    try:
        if start_time:
            datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S")
        if end_time:
            datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S")
    except ValueError:
        raise HTTPException(status_code=400, detail="时间格式错误，应为 YYYY-MM-DD HH:MM:SS")
    
    # 验证文件类型
    if file_type and file_type not in ["photo", "video", "audio", "document", "other"]:
        raise HTTPException(status_code=400, detail="无效的文件类型")
    
    # 调用服务层查询文件
    result = search_files(
        db=db,
        user_id=current_user.id,
        file_type=file_type,
        start_time=start_time,
        end_time=end_time,
        keyword=keyword,
        file_hash=file_hash,
        page=page,
        page_size=page_size,
        is_delete=is_delete,
        order_by=order_by,
        order_desc=order_desc,
        directory_id=directory_id
    )
    
    # 构造返回结果，符合PaginatedResponse格式
    response_data = PaginatedResponse(
        total=result["total"],
        page=result["page"],
        page_size=result["page_size"],
        items=[FileResponse.from_orm(file) for file in result["files"]]
    )
    
    logger.debug(f"查询到 {result['total']} 条记录")
    return ResponseResult[PaginatedResponse[FileResponse]](
        code=200,
        message="查询成功",
        data=response_data,
        timestamp=int(time.time() * 1000)
    )

@router.delete("/files/{file_id}",
    summary="删除单个文件",
    description="删除指定ID的文件。默认为软删除（移至回收站），可选择永久删除（从存储中彻底移除）。",
    tags=["文件管理"],
    response_model=ResponseResult[Dict[str, Any]]
)
async def delete_file_endpoint(
    file_id: int = Path(..., description="文件ID"),
    current_user: User = Depends(get_current_user_from_token),
    permanent: bool = Query(False, description="是否永久删除，默认为软删除"),
    db: Session = Depends(get_db)
):
    """删除文件
    
    默认进行软删除（移至回收站），如果指定permanent=true则永久删除
    
    返回:
        - **message**: 操作结果信息
        - **is_permanent**: 是否执行了永久删除
    """
    logger.debug(f"接收到删除请求: file_id={file_id}, user_id={current_user.id}, permanent={permanent}")
    
    # 验证用户是否存在
    user = get_user_by_id(db, current_user.id)
    if not user:
        raise HTTPException(status_code=404, detail="用户不存在")
    
    # 调用服务层删除文件
    result = delete_file(db=db, file_id=file_id, user_id=current_user.id, permanent=permanent)
    
    message = "文件永久删除成功" if permanent else "文件已移至回收站"
    return ResponseResult[Dict[str, Any]](
        code=200,
        message=message,
        data={"is_permanent": permanent},
        timestamp=int(time.time() * 1000)
    )

class BatchDeleteRequest(BaseModel):
    """批量删除请求模型"""
    file_ids: List[int] = Field(..., description="要删除的文件ID列表", example=[1, 2, 3])
    permanent: bool = Field(False, description="是否永久删除文件，True表示从存储中彻底移除，False表示标记为已删除")
    
    class Config:
        schema_extra = {
            "example": {
                "file_ids": [1, 2, 3],
                "permanent": False
            }
        }

@router.post("/files/batch-delete", 
    summary="批量删除文件",
    description="批量删除多个文件。默认为软删除（移至回收站），可选择永久删除（从存储中彻底移除）。提供详细的操作结果统计。",
    response_description="批量删除操作的结果统计",
    tags=["文件管理"],
    response_model=ResponseResult[Dict[str, Any]]
)
async def batch_delete_files_endpoint(
    request: BatchDeleteRequest,
    current_user: User = Depends(get_current_user_from_token),
    db: Session = Depends(get_db)
):
    """批量删除文件
    
    - **request**: 包含文件ID列表和是否永久删除的请求体
    
    返回:
        - **success_count**: 成功删除的文件数
        - **failed_count**: 删除失败的文件数
        - **failed_files**: 删除失败的文件列表，包含文件ID和失败原因
    """
    logger.info(f"接收到批量删除请求: user_id={current_user.id}, file_ids={request.file_ids}, permanent={request.permanent}")
    
    # 调用批量删除服务
    result = batch_delete_files(
        db=db,
        file_ids=request.file_ids,
        user_id=current_user.id,
        permanent=request.permanent
    )
    
    message = "批量删除操作完成"
    if result["success_count"] > 0:
        message = f"成功删除 {result['success_count']} 个文件"
        if result["failed_count"] > 0:
            message += f"，{result['failed_count']} 个文件删除失败"
    
    return ResponseResult[Dict[str, Any]](
        code=200,
        message=message,
        data=result,
        timestamp=int(time.time() * 1000)
    )

@router.put("/files/{file_id}/rename",
    summary="重命名文件",
    description="修改指定ID文件的名称，保留文件的其他属性和内容不变。",
    tags=["文件管理"],
    response_model=ResponseResult[Dict[str, Any]]
)
async def rename_file_endpoint(
    file_id: int = Path(..., description="文件ID"),
    current_user: User = Depends(get_current_user_from_token),
    new_name: str = Query(..., description="新文件名"),
    db: Session = Depends(get_db)
):
    """重命名文件
    
    只修改文件名，不改变文件的其他属性和内容
    
    返回:
        - **message**: 操作结果信息
        - **new_name**: 更新后的文件名
    """
    logger.debug(f"接收到重命名请求: file_id={file_id}, user_id={current_user.id}, new_name={new_name}")
    
    # 验证用户是否存在
    user = get_user_by_id(db, current_user.id)
    if not user:
        raise HTTPException(status_code=404, detail="用户不存在")
    
    # 验证新文件名不为空
    if not new_name.strip():
        raise HTTPException(status_code=400, detail="新文件名不能为空")
    
    # 调用服务层重命名文件
    result = rename_file(db=db, file_id=file_id, user_id=current_user.id, new_name=new_name)
    
    return ResponseResult[Dict[str, Any]](
        code=200,
        message="文件重命名成功",
        data={"new_name": new_name},
        timestamp=int(time.time() * 1000)
    )

class BatchRestoreRequest(BaseModel):
    """批量恢复请求模型"""
    file_ids: List[int] = Field(..., description="要恢复的文件ID列表", example=[1, 2, 3])
    
    class Config:
        schema_extra = {
            "example": {
                "file_ids": [1, 2, 3]
            }
        }

@router.post("/files/batch-restore",
    summary="批量恢复文件",
    description="从回收站中批量恢复多个已删除的文件。提供详细的操作结果统计，包括成功和失败的文件列表。",
    response_description="批量恢复操作的结果统计",
    tags=["文件管理"],
    response_model=ResponseResult[Dict[str, Any]]
)
async def batch_restore_files_endpoint(
    request: BatchRestoreRequest,
    current_user: User = Depends(get_current_user_from_token),
    db: Session = Depends(get_db)
):
    """批量恢复文件
    
    - **request**: 包含要恢复的文件ID列表的请求体
    
    返回:
        - **success_count**: 成功恢复的文件数
        - **failed_count**: 恢复失败的文件数
        - **failed_files**: 恢复失败的文件列表，包含文件ID和失败原因
    """
    logger.info(f"接收到批量恢复请求: user_id={current_user.id}, file_ids={request.file_ids}")
    
    # 调用批量恢复服务
    result = batch_restore_files(
        db=db,
        file_ids=request.file_ids,
        user_id=current_user.id
    )
    
    message = "批量恢复操作完成"
    if result["success_count"] > 0:
        message = f"成功恢复 {result['success_count']} 个文件"
        if result["failed_count"] > 0:
            message += f"，{result['failed_count']} 个文件恢复失败"
    
    return ResponseResult[Dict[str, Any]](
        code=200,
        message=message,
        data=result,
        timestamp=int(time.time() * 1000)
    )

@router.get("/files/{file_id}/preview",
    summary="获取文件预览链接",
    description="获取指定文件的预览URL，支持所有类型文件。对于图片和视频文件，可直接在浏览器中预览；其他类型文件可以下载后预览或使用第三方服务预览。",
    tags=["文件管理"],
    response_model=ResponseResult[Dict[str, Any]]
)
async def preview_file(
    file_id: int = Path(..., description="文件ID"),
    current_user: User = Depends(get_current_user_from_token),
    db: Session = Depends(get_db)
):
    """获取文件预览链接
    
    返回:
        - **url**: 预览URL
        - **file_type**: 文件类型(photo/video/audio/document/other)
        - **mime_type**: MIME类型
        - **file_name**: 文件名
        - **file_size**: 文件大小(字节)
        - **extension**: 文件扩展名
        - **direct_preview**: 是否支持直接预览(true/false)
    """
    logger.debug(f"接收到文件预览请求: file_id={file_id}, user_id={current_user.id}")
    
    # 调用服务层获取预览URL
    result = get_file_preview_url(db=db, file_id=file_id, user_id=current_user.id)
    
    return ResponseResult[Dict[str, Any]](
        code=200,
        message="获取预览链接成功",
        data=result,
        timestamp=int(time.time() * 1000)
    )

@router.get("/files/{file_id}/download",
    summary="获取文件下载链接",
    description="获取指定文件的临时下载URL，有效期1小时。直接访问返回的URL即可下载文件。",
    tags=["文件管理"],
    response_model=ResponseResult[Dict[str, Any]]
)
async def download_file(
    file_id: int = Path(..., description="文件ID"),
    current_user: User = Depends(get_current_user_from_token),
    db: Session = Depends(get_db)
):
    """获取文件下载链接
    
    返回:
        - **url**: 下载URL
        - **file_name**: 文件名
        - **file_size**: 文件大小
        - **mime_type**: MIME类型
    """
    logger.debug(f"接收到文件下载请求: file_id={file_id}, user_id={current_user.id}")
    
    # 调用服务层获取下载URL
    result = get_file_download_url(db=db, file_id=file_id, user_id=current_user.id)
    
    return ResponseResult[Dict[str, Any]](
        code=200,
        message="获取下载链接成功",
        data=result,
        timestamp=int(time.time() * 1000)
    ) 